package core

import "bytes"

type NodeType string

const (
	BOOLEAN_NODE = "BOOLEAN_NODE"
	SYMBOL_NODE  = "SYMBOL_NODE"
	LIST_NODE    = "LIST_NODE"
)

// Node represents a value in the Scheme environment
// It's the interface that all Scheme values must implement
type Node interface {
	// Type returns the type of the object
	Type() NodeType
	String() string
}

type Expression = Node

type BooleanNode struct {
	token Token
	value bool
}

func (b *BooleanNode) Type() NodeType {
	return BOOLEAN_NODE
}

func (b *BooleanNode) String() string {
	return b.token.Lexeme
}

type SymbolNode struct {
	token Token
	value string
}

func (s *SymbolNode) Type() NodeType {
	return SYMBOL_NODE
}

func (s *SymbolNode) String() string {
	return s.token.Lexeme
}

type ListNode struct {
	nodes []Node
}

func (l *ListNode) Type() NodeType {
	return LIST_NODE
}

func (l *ListNode) String() string {
	var out bytes.Buffer
	out.WriteString("(")
	for i, o := range l.nodes {
		if i != 0 {
			out.WriteString(" ")
		}
		out.WriteString(o.String())
	}
	out.WriteString(")")
	return out.String()
}
